package test.auth;

import java.awt.Desktop;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import org.abettor.angleworm.auth.HttpsSocketFactory;
import org.abettor.angleworm.util.Configuration;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.protocol.Protocol;
import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;

public class YahooOAuth
{
	public static void main(String[] args) throws HttpException, IOException, URISyntaxException
	{
		String requestTokenURL = Configuration.getGlobalProperty("auth.yahoo.oauth.requestToken.url");
		String userAuthorizationURL = Configuration.getGlobalProperty("auth.yahoo.oauth.userAuth.url");
		String accessTokenURL = Configuration.getGlobalProperty("auth.yahoo.oauth.accessToken.url");
		String callbackURL = Configuration.getGlobalProperty("auth.yahoo.oauth.callback.url");
		String consumerKey = Configuration.getGlobalProperty("auth.yahoo.oauth.consumerKey");
		String consumerSecret = Configuration.getGlobalProperty("auth.yahoo.oauth.consumerSecret");

		ProtocolSocketFactory psf = new HttpsSocketFactory("yahoo", "www.yahoo.com");
		Protocol protocol = new Protocol("https", psf, 443);
		Protocol.registerProtocol("https", protocol);

		//--------------获取 Request Token

		List<NameValuePair> paramList = new ArrayList<NameValuePair>();
		paramList.add(new NameValuePair("oauth_consumer_key", consumerKey));
		paramList.add(new NameValuePair("oauth_nonce", "NONCE" + System.currentTimeMillis()));
		paramList.add(new NameValuePair("oauth_signature_method", "PLAINTEXT"));
		paramList.add(new NameValuePair("oauth_signature", consumerSecret + "&"));//!!!这里要注意，必须加这个“&”
		paramList.add(new NameValuePair("oauth_timestamp", "" + System.currentTimeMillis() / 1000L));
		paramList.add(new NameValuePair("oauth_version", "1.0"));
		paramList.add(new NameValuePair("xoauth_lang_pref", "en-us"));
		paramList.add(new NameValuePair("oauth_callback", callbackURL));
		NameValuePair[] params = new NameValuePair[paramList.size()];
		paramList.toArray(params);

		PostMethod getReqTokenMthd = new PostMethod(requestTokenURL);
		getReqTokenMthd.addRequestHeader("Content-type", "application/x-www-form-urlencoded");
		getReqTokenMthd.addParameters(params);

		HttpClient hc = new HttpClient();
		int status = hc.executeMethod(getReqTokenMthd);
		if(status != HttpStatus.SC_OK)
		{
			System.out.println("获取 Request Token 失败！");
			System.out.println("\tHTTP Status: " + status);
			String body = getReqTokenMthd.getResponseBodyAsString();
			System.out.println("----------\n" + body);
			getReqTokenMthd.releaseConnection();
			return;
		}

		String body = getReqTokenMthd.getResponseBodyAsString();
		getReqTokenMthd.releaseConnection();
		String[] retVals = body.split("\\&");
		Properties propRequestToken = new Properties();
		for(String str : retVals)
		{
			if(str != null && ! str.isEmpty())
			{
				int idx = str.indexOf("=");
				if(idx <= 0 || idx == str.length() - 1)
				{
					continue;
				}

				String key = str.substring(0, idx);
				String val = str.substring(idx + 1);
				propRequestToken.setProperty(key, val);
				System.out.println(key + " -> " + val);
			}
		}

		//-------------获取用户身份认证

		String authToken = propRequestToken.getProperty("oauth_token");
		if(authToken == null || authToken.isEmpty())
		{
			System.out.println("没有找到正确的 oauth_token 值！");
			return;
		}

		String uiUrl = userAuthorizationURL + "?oauth_token=" + authToken;
		Desktop desktop = Desktop.getDesktop();
		desktop.browse(new URI(uiUrl));
		System.out.println("Browsing URL " + uiUrl + "...");

		//------------获取 Access Token

		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		System.out.print("Yahoo! 登录代码：");
		String verifier = br.readLine();
		String authTokenSecret = propRequestToken.getProperty("oauth_token_secret");

		paramList = new ArrayList<NameValuePair>();
		paramList.add(new NameValuePair("oauth_consumer_key", consumerKey));
		paramList.add(new NameValuePair("oauth_nonce", "NONCE" + System.currentTimeMillis()));
		paramList.add(new NameValuePair("oauth_signature_method", "PLAINTEXT"));
		paramList.add(new NameValuePair("oauth_signature", consumerSecret + "&" + authTokenSecret));
		paramList.add(new NameValuePair("oauth_timestamp", "" + System.currentTimeMillis() / 1000L));
		paramList.add(new NameValuePair("oauth_version", "1.0"));
		paramList.add(new NameValuePair("oauth_verifier", verifier));
		paramList.add(new NameValuePair("oauth_token", authToken));
		params = new NameValuePair[paramList.size()];
		paramList.toArray(params);

		PostMethod getAccTokenMthd = new PostMethod(accessTokenURL);
		getAccTokenMthd.addRequestHeader("Content-type", "application/x-www-form-urlencoded");
		getAccTokenMthd.addParameters(params);

		hc = new HttpClient();
		status = hc.executeMethod(getAccTokenMthd);
		if(status != HttpStatus.SC_OK)
		{
			System.out.println("获取 Request Token 失败！");
			System.out.println("\tHTTP Status: " + status);
			body = getAccTokenMthd.getResponseBodyAsString();
			System.out.println("----------\n" + body);
			getAccTokenMthd.releaseConnection();
			return;
		}

		body = getAccTokenMthd.getResponseBodyAsString();
		getAccTokenMthd.releaseConnection();
		retVals = body.split("\\&");
		Properties propAccessToken = new Properties();
		for(String str : retVals)
		{
			if(str != null && ! str.isEmpty())
			{
				int idx = str.indexOf("=");
				if(idx <= 0 || idx == str.length() - 1)
				{
					continue;
				}

				String key = str.substring(0, idx);
				String val = str.substring(idx + 1);
				propAccessToken.setProperty(key, val);
			}
		}

		String guid = propAccessToken.getProperty("xoauth_yahoo_guid");
		if(guid == null || guid.isEmpty())
		{
			System.out.println("登录验证失败！");
			return;
		}

		for(Object obj : propAccessToken.keySet())
		{
			System.out.println(obj + " -> " + propAccessToken.get(obj));
		}
	}
}
